﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using devtm.Helpers;
using devtm.Types.LazyLoading;
using Microsoft.Win32;
using devtm.Collections;
using System.Linq;
using Fluent;

namespace devtm.Editor.Configuration.formWpf
{
    /// <summary>
    /// Interaction logic for SelectAssembly.xaml
    /// </summary>
    public partial class SelectAssembly : RibbonWindow
    {

        string[] _filenames;

        private ICollectionView viewAssemblies;
        IEnumerable<DirectoryInfo> _dirs;
        public SelectAssembly(IEnumerable<DirectoryInfo> dirs, TypeContraint isolateType)
        {

            InitializeComponent();

            Datas.ListeAssemblies.Events += ListeAssemblies_Events;
            _IsolateType = isolateType;
            this._dirs = dirs;
            button1.IsEnabled = false;

            TreeViewItemSelected = new DisplayTypeConstructor(_IsolateType, null);
            TreeSelectType.Items.Add(TreeViewItemSelected);

            LstFile.ItemsSource = Datas.ListeAssemblies;

            if (_IsolateType != null)
            {
                viewAssemblies = CollectionViewSource.GetDefaultView(LstFile.ItemsSource);
                if (viewAssemblies.CanFilter)
                    viewAssemblies.Filter = c => (c as AssemblyNamespace).Loaded && ContainsGoodType((c as AssemblyNamespace));
            }



            // refresh apres le load
        }

        private bool ContainsGoodType(AssemblyNamespace c)
        {

            foreach (Type item in c)
                if (Filter(item))
                    return true;

            return false;
        }



        public SelectAssembly(IEnumerable<DirectoryInfo> dirs, TypeContraint isolateType, params string[] filenames)
            : this(dirs, isolateType)
        {

            _filenames = filenames;
            foreach (string item in _filenames)
            {
                if (String.IsNullOrEmpty(item))
                    continue;
                FileInfo f = new FileInfo(item);
                AddDirectory(f.Directory);
            }
        }


        public event EventHandler<AddEventArgs> FileAdded;

        
        /// <summary>
        /// Gets or sets the currentdirectory.
        /// </summary>
        /// <value>The currentdirectory.</value>
        public void AddDirectory(DirectoryInfo newdirectory)
        {

            Datas.LoadTypes(new List<DirectoryInfo> { newdirectory });

            if (!Datas.DirectoriesSearch.ContainsKeyFrom(newdirectory))
                Datas.DirectoriesSearch.Add(newdirectory);

            Datas.LoadTypes(Datas.DirectoriesSearch);
            
        }


        #region Filter


        /// <summary>
        /// Filters the load assembly.
        /// </summary>
        /// <param name="c">The c.</param>
        /// <returns></returns>
        //public bool FilterLoadAssembly(AssemblyNamespace c)
        //{

        //    if (_filenames != null)
        //    foreach (string item in _filenames)
        //    {
        //        if (String.IsNullOrEmpty(item))
        //            continue;

        //        if (c is AssemblyFileNamespace)
        //        {
        //            if (c.Filename == item)
        //            {
        //                c.MustLoad = true;
        //                Datas.jobs.Add(() => c.Initialize());
        //                Datas.jobs.Add(() => c.LoadTypes());
        //                return true;                        
        //            }
        //        }
        //    }

        //    bool i = false;
        //    if (_IsolateType != null)
        //    {
        //        if (c.Loaded)
        //            return false;
        //        string jj = _IsolateType._type.Assembly.FullName;
        //        i = jj.StartsWith(c.SingleName);

        //        if (i)
        //            c.MustLoad = true;
        //    }

        //    return i;

        //}

        /// <summary>
        /// Test si le type corresponds
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        private bool Filter(Type type)
        {

            if (_IsolateType == null)
                return true;

            if (TreeViewItemSelected.Contraint.IsValid(type))
            {
                AddEventArgs evnt = new AddEventArgs { Cancel = false, Tag = type, Context = "file" };
                if (FileAdded != null) FileAdded(this, evnt);
                return !evnt.Cancel;
            }

            return false;
            
        }

        //private bool FilterText(object c)
        //{

        //    DescType d = (c as devtm.Types.LazyLoading.DescType);  

        //    string txt = string.Empty;
        //    try
        //    {
        //        txt = textSearch.Text;
        //    }
        //    catch (Exception) { }

        //    if (String.IsNullOrEmpty(txt))
        //        return true;

        //    return d.Type.FullName.ToLower().Contains(textSearch.Text.ToLower());
        //}

        private TypeContraint _IsolateType;
       
        #endregion

        
        private void LstFile_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 0)
                return;

            devtm.Types.LazyLoading.AssemblyNamespace i = (e.AddedItems[0] as devtm.Types.LazyLoading.AssemblyNamespace);

            if (!i.Initialized && !i.IsInError)
            {
                i.Initialize();
                if (i.Initialized && !i.IsInError)
                    i.LoadTypes();

            }


            LstType.ItemsSource = i;

            viewAssemblies = CollectionViewSource.GetDefaultView(i);
            if (viewAssemblies.CanFilter)
                viewAssemblies.Filter = c => Filter((Type)c);

        } 


        public Type TypeRetour { get; set; }
        public String Retour { get; set; }
        //public FileInfo FileAssembly { get; set; }


        private void button2_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        protected override void OnClosed(EventArgs e)
        {
            Datas.ListeAssemblies.Events -= ListeAssemblies_Events;
            base.OnClosed(e);
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {

            TypeRetour = (TreeSelectType.Items[0] as DisplayTypeConstructor).build();       //(LstType.SelectedItem as Type);
            Retour = TypeRetour.AssemblyQualifiedName;
            this.Close();
        }

        private void LstType_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.Title = SelectedItem;
            Type t = (LstType.SelectedItem as Type);
            TreeViewItemSelected.SelectedType = t;

            button1.IsEnabled = false;
            try
            {
                Type t1 = (TreeSelectType.Items[0] as DisplayTypeConstructor).build();
                button1.IsEnabled = true;
            }
            catch (Exception)
            {

               // throw;
            }
        }

        String SelectedItem
        {
            get
            {

                if (LstType.SelectedItem == null)
                    return string.Empty;

                return (LstType.SelectedItem as Type).AssemblyQualifiedName;

            }

        }

        /// <summary>
        /// Import
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>        
        private void button3_Click(object sender, RoutedEventArgs e)
        {

            OpenFileDialog file = new OpenFileDialog();
            file.InitialDirectory = Datas.FileConfiguration.Directory.FullName;
            file.Filter= "Libraries file (*.dll)|*.dll";

            file.ShowDialog(this);

            var items = file.OpenFiles();

            String Ref1 = Datas.FileConfiguration.Directory.FullName;

            foreach (FileStream item in items)
            {
                FileInfo f = new FileInfo(item.Name);
                Datas.AddDirectoryLibrary(f.Directory);
                AddDirectory(f.Directory);
            }

        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {

            ICollectionView view = CollectionViewSource.GetDefaultView(Datas.ListeAssemblies);
            if (view.CanFilter)
                view.Filter = c => FilterFullAssembly((AssemblyNamespace)c);

        }

        private void TypeDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (LstType.SelectedItem == null)
                return;

            button1_Click(this, null);

        }

        //private void EventFilterAssemblies(object sender, RoutedEventArgs e)
        //{

        //    LstFile.ItemsSource = Datas.ListeAssemblies;

        //    ICollectionView view = CollectionViewSource.GetDefaultView(Datas.ListeAssemblies);
        //    if (view.CanFilter)
        //        view.Filter = c => FilterFullAssembly((AssemblyNamespace)c);

        //}

        private bool FilterFullAssembly(AssemblyNamespace c)
        {

            string txt = string.Empty;
            try
            {
                txt = textSearch.Text;
            }
            catch (Exception) { }

            if (String.IsNullOrEmpty(txt))
                return true;

            return c.Name.ToLower().Contains(textSearch.Text.ToLower());


            //if (c is AssemblyFileNamespace)
                //return (c as AssemblyFileNamespace).Name.Contains(textSearch.Text);
            //else
                //return (c as AssemblyGacNamespace).Name.Contains(textSearch.Text);

        }

        private void LoadAll(object sender, RoutedEventArgs e)
        {

            foreach (var i in Datas.ListeAssemblies)
            
                if (!i.Initialized && !i.IsInError)
                {
                    i.Initialize();
                    if (i.Initialized && !i.IsInError)
                        i.LoadTypes();

                }

        }

        private void TreeNodeSelectedChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {

            if (!TreeSelectType.IsEnabled)
                return;

            TreeViewItemSelected = (DisplayTypeConstructor)TreeSelectType.SelectedItem;
            txtbox.Content = TreeViewItemSelected.Contraint.Description;


            AssemblyNamespace ii = (AssemblyNamespace)LstFile.SelectedItem;

            ICollectionView view = CollectionViewSource.GetDefaultView(ii);
            if (view == null)
                return;

            if (view.CanFilter)
                view.Filter = c => Filter((Type)c);

        }



        public DisplayTypeConstructor TreeViewItemSelected { get; set; }



        void ListeAssemblies_Events(object sender, ListeAssembliesEventArgs e)
        {

            if (e.MethodName == "LoadTypes")
                viewAssemblies.Refresh();
        }

    }
}
